home *** CD-ROM | disk | FTP | other *** search
- unit SystemInfo;
-
- interface
-
- Const
- BoolArray : Array[False..True] of String = ('No','Yes');
-
- Function GetTerminalServicesInfo : String;
- Function GetSystemInfo : String;
- Function GetTimeAndDateInfo : String;
- Function GetKeyboardLayoutInfo : String;
- Function GetAudioDeviceInfo : String;
- Function GetMiscInfo : String;
- Function GetWinSockInfo : String;
- Function GetInternetConnectionInfo : String;
-
- implementation
-
- Uses
- Windows,Registry,SysUtils,MMSystem,Printers;
-
- Const
- { Constants from WINNT.H }
- siaSecurityNTAuthority : TSIDIdentifierAuthority = (Value: (0,0,0,0,0,5));
- SECURITY_BUILTIN_DOMAIN_RID = $20;
- DOMAIN_ALIAS_RID_ADMINS = $220;
- SM_REMOTESESSION = $1000; { from WinUser.h }
-
- Var
- CurrentHostName : String;
-
- Function GetTerminalServicesInfo : String;
- Var B : Boolean;
- Begin
- Result := 'Running under Terminal Services: ';
- If ((Win32Platform = VER_PLATFORM_WIN32_NT) And
- (Win32MajorVersion >= 5)) Then Begin { Windows 2000 or later }
- B := (GetSystemMetrics(SM_REMOTESESSION) <> 0);
- Result := Result+BoolArray[B];
- End
- Else Result := Result+'(cannot determine)';
- End;
-
- Function RunningAsAdministrator : Boolean;
- Var
- hThread : THandle;
- ptgTokenGroups : PTokenGroups;
- intTokenGroups : Cardinal;
- intGroup : Integer;
- psidAdmin : PSID;
-
- Begin
- Result := False;
- { First we must open a handle to the access token for this thread. }
- If (Not OpenThreadToken(GetCurrentThread,TOKEN_QUERY,False,hThread)) Then Begin
- If (GetLastError = Error_No_Token) Then Begin
- {
- If the thread does not have an access token, we'll examine the
- access token associated with the process.
- }
- If (Not OpenProcessToken(GetCurrentProcess,TOKEN_QUERY,hThread)) Then Exit;
- End
- Else Exit;
- End;
- {
- Then we must query the size of the group information associated with
- the token. Note that we expect a FALSE result from GetTokenInformation
- because we've given it a NULL buffer. On exit cbTokenGroups will tell
- the size of the group information.
- }
- If GetTokenInformation(hThread,TokenGroups,nil,0,intTokenGroups) Then Exit;
- { Here we verify that GetTokenInformation failed for lack of a large enough buffer. }
- If (GetLastError <> Error_Insufficient_Buffer) Then Exit;
- {
- Now we allocate a buffer for the group information. Since _alloca allocates on
- the stack, we don't have to explicitly deallocate it. That happens automatically
- when we exit this function.
- }
- GetMem(ptgTokenGroups,intTokenGroups);
- {
- Now we ask for the group information again. This may fail if an administrator
- has added this account to an additional group between our first call to
- GetTokenInformation and this one.
- }
- If (Not GetTokenInformation(hThread,TokenGroups,ptgTokenGroups,
- intTokenGroups,intTokenGroups)) Then Exit;
- { Now we must create a System Identifier for the Admin group. }
- If (Not AllocateAndInitializeSid(siaSecurityNTAuthority,2,SECURITY_BUILTIN_DOMAIN_RID,
- DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,psidAdmin)) Then Exit;
- {
- Finally we'll iterate through the list of groups for this access token looking for
- a match against the SID we created above.
- }
- For intGroup := 0 to ptgTokenGroups^.GroupCount-1 do Begin
- {$R-}
- If EqualSid(ptgTokenGroups^.Groups[intGroup].Sid,psidAdmin) Then Begin
- {$R+}
- Result := True;
- Break;
- End;
- End;
- { Before we exit we must explicity deallocate the SID we created. }
- FreeSid(psidAdmin);
- FreeMem(ptgTokenGroups,intTokenGroups);
- End;
-
- Function GetNTType : String;
- Var
- R : TRegistry;
- S : String;
-
- Begin
- R := TRegistry.Create;
- R.RootKey := HKEY_LOCAL_MACHINE;
- R.OpenKey('SYSTEM\CurrentControlSet\Control\ProductOptions',False);
- S := UpperCase(R.ReadString('ProductType'));
- R.Free;
- If (S = 'WINNT') Then Result := 'Workstation'
- Else If (S = 'SERVERNT') Then Result := 'Server'
- Else If (S = 'LANMANNT') Then Result := 'Advanced Server'
- Else Result := '(unknown)';
- End;
-
- Function NetWkstaUserGetInfo(ServerName : PWideChar; Level : Integer;
- Buf : Pointer) : Integer; StdCall External 'netapi32.dll';
-
- Const
- nerr_Success = 0;
-
- Type
- PWkstaUserInfo_1 = ^TWkstaUserInfo_1;
- TWkstaUserInfo_1 = Record
- UserName : PWideChar;
- LogonDomain : PWideChar;
- OtherDomains : PWideChar;
- LogonServer : PWideChar;
- End;
-
- Function GetNetworkUserLogonInfo(LocalComputerName : String) : String;
- Var Buf : TWkstaUserInfo_1;
- Begin
- FillChar(Buf,SizeOf(Buf),0);
- Result := '(unknown)';
- If (NetWkstaUserGetInfo(nil,1,@Buf) = nerr_Success) Then Begin
- With Buf do Begin
- Result := 'Logon Domain: ';
- If (LogonDomain = nil) Then Result := Result+LocalComputerName
- Else Result := Result+WideCharToString(LogonDomain);
- Result := Result+#13#10'Logon Server: ';
- If (LogonServer = nil) Then Result := Result+LocalComputerName
- Else Result := Result+WideCharToString(LogonServer);
- End;
- End;
- End;
-
- Function GetGlobalMemoryStatus : String;
- Var MS : TMemoryStatus;
- Begin
- MS.dwLength := SizeOf(MS);
- GlobalMemoryStatus(MS);
- With MS do Begin
- Result := 'Total Physical: '+IntToStr(dwTotalPhys div 1024)+' kB'+#13#10+
- 'Available Physical: '+IntToStr(dwAvailPhys div 1024)+' kB'+#13#10+
- 'Total Page File: '+IntToStr(dwTotalPageFile div 1024)+' kB'+#13#10+
- 'Available Page File: '+IntToStr(dwAvailPageFile div 1024)+' kB'+#13#10+
- 'Total Virtual: '+IntToStr(dwTotalVirtual div 1024)+' kB'+#13#10+
- 'Available Physical: '+IntToStr(dwAvailVirtual div 1024)+' kB';
- End;
- End;
-
- Function GetEnvironmentVariable(Name : String) : String;
- Var I : Integer;
- Begin
- Result := '(cannot determine)';
- I := Windows.GetEnvironmentVariable(PChar(Name),nil,0);
- If (I > 0) Then Begin
- SetLength(Result,I-1);
- Windows.GetEnvironmentVariable(PChar(Name),PChar(Result),I);
- End;
- end;
-
- Function GetSystemInfo : String;
- Var
- P : Array[0..255] of Char;
- I : Cardinal;
- S : String;
- SI : TSystemInfo;
- B : Boolean;
-
- Begin
- I := SizeOf(P);
- If (Not GetUserName(P,I)) Then StrPCopy(P,SysErrorMessage(GetLastError));
- Result := 'Current User: '+String(P)+#13#10;
- I := SizeOf(P);
- Result := Result+'Administrator priviledges: '+BoolArray[RunningAsAdministrator]+#13#10;
- If (Not GetComputerName(P,I)) Then StrPCopy(P,SysErrorMessage(GetLastError));
- Result := Result+'Computer Name: '+String(P)+#13#10;
- CurrentHostName := String(P);
- Windows.GetSystemInfo(SI);
- Result := Result+'Processor count: '+IntToStr(SI.dwNumberOfProcessors)+' '+#13#10+
- 'Processor level: '+IntToStr(SI.wProcessorLevel)+#13#10;
- If (SI.wProcessorLevel >= 5) Then Begin { only Pentium or above can have MMX instructions }
- Asm
- mov B,False { clear flag }
- mov eax,1 { request feature flags }
- db $0F,$A2 { CPUID instruction opcode 0FA2h }
- test edx,$00800000 { Is bit 23 in feature flags set? }
- jz @@notfound
- mov B,True { yes, we have MMX! }
- @@notfound:
- End;
- End;
- Result := Result+'Flawed Pentium division: '+BoolArray[(TestFDIV = -1)]+#13#10;
- Result := Result+'Supports MMX instructions: '+BoolArray[B]+#13#10#13#10;
- Case Win32Platform of
- Ver_Platform_Win32_Windows : S := 'Win95/98';
- Ver_Platform_Win32_NT : S := 'Windows NT '+GetNTType;
- Else S := 'Other';
- End;
- Result := Result+'OS Version: '+S+' '+IntToStr(Win32MajorVersion)+'.'+
- IntToStr(Win32MinorVersion)+', Build '+
- IntToStr(Win32BuildNumber)+', '+Win32CSDVersion+#13#10;
- S := GetNetworkUserLogonInfo(String(P));
- If (S <> '') Then Result := Result+S+#13#10;
- If (GetSystemDirectory(P,SizeOf(P)) = 0) Then
- StrPCopy(P,SysErrorMessage(GetLastError));
- Result := Result+'System directory: '+String(P)+#13#10;
- If (GetWindowsDirectory(P,SizeOf(P)) = 0) Then
- StrPCopy(P,SysErrorMessage(GetLastError));
- Result := Result+'Windows directory: '+String(P)+#13#10+
- 'TEMP environment variable: '+
- GetEnvironmentVariable('TEMP')+#13#10+
- 'SYSTEMROOT environment variable: '+
- GetEnvironmentVariable('SYSTEMROOT')+#13#10+
- #13#10+GetGlobalMemoryStatus;
- With Printer do Begin
- Result := Result+#13#10#13#10+'Printers installed:';
- For I := 0 to Printers.Count-1 do
- Result := Result+#13#10+IntToStr(I)+': '+Printers[I];
- End;
- End;
-
- Function GetTimeAndDateInfo : String;
- Const Time_Zone_Id_Daylight = 2; { from MAPIWIN.H }
- Var
- TZInfo : TTimeZoneInformation;
- I : Integer;
- DST : Boolean;
-
- Begin
- Result := 'Current time: '+DateTimeToStr(Now);
- I := GetTimeZoneInformation(TZInfo);
- If (I <> -1) Then Begin
- DST := (I = Time_Zone_Id_Daylight);
- Result := Result+#13#10+'Daylight savings time: '+BoolArray[DST];
- Result := Result+#13#10+'Time zone: ';
- If DST Then Result := Result+WideCharToString(TZInfo.DaylightName)
- Else Result := Result+WideCharToString(TZInfo.StandardName);
- Result := Result+#13#10'Time zone bias: '+IntToStr(-TZInfo.Bias)+' min';
- End;
- End;
-
- Function GetKeyboardLayoutInfo : String;
- Var
- HKLs : Array[1..100] of Integer;
- I,J : Integer;
-
- Begin
- J := GetKeyboardLayoutList(100,HKLs);
- Result := 'Keyboard layouts: '+IntToStr(J)+#13#10;
- For I := 1 to J do Begin
- Result := Result+'Device handle: '+IntToStr(HKLs[I] shr 16)+' '+
- 'Language ID: '+IntToStr(HKLs[I] And $FFFF)+#13#10;
- End;
- If GetKeyboardLayoutName(@HKLs) Then { notice re-use of HKLs array }
- Result := Result+'Default layout name: '+PChar(@HKLs);
- End;
-
- Function GetAudioDeviceInfo : String;
- Var
- I,J : Integer;
- IC : TWaveInCaps;
- OC : TWaveOutCaps;
-
- Begin
- J := WaveInGetNumDevs;
- Result := 'Wave input devices: '+IntToStr(J)+#13#10;
- For I := 1 to J do Begin
- If (WaveInGetDevCaps(I-1,@IC,SizeOf(IC)) = MMSysErr_NoError) Then
- Result := Result+'In #'+IntToStr(I)+': '+String(IC.szPname)+#13#10;
- End;
- J := WaveOutGetNumDevs;
- Result := Result+'Wave output devices: '+IntToStr(J)+#13#10;
- For I := 1 to J do Begin
- If (WaveOutGetDevCaps(I-1,@OC,SizeOf(OC)) = MMSysErr_NoError) Then
- Result := Result+'Out #'+IntToStr(I)+': '+String(OC.szPname)+#13#10;
- End;
- SetLength(Result,Length(Result)-2); { delete last CRLF }
- End;
-
- Function GetMiscInfo : String;
- Var B : Bool;
- Begin
- SystemParametersInfo(spi_GetDragFullWindows,0,@B,0);
- Result := 'Drag full windows: '+BoolArray[B]+#13#10;
- SystemParametersInfo(spi_GetScreenSaveActive,0,@B,0);
- Result := Result+'Screen saver set: '+BoolArray[B];
- End;
-
- Type
- PWSAData = ^TWSAData;
- TWSAData = Packed Record
- Version : Word;
- HighVersion : Word;
- Description : Array[0..256] of Char;
- SystemStatus : Array[0..128] of Char;
- { record continues but we don't care... }
- End;
-
- TWSAStartup = Function(Version : Word; Data : Pointer) : Integer; StdCall;
- TWSACleanup = Function : Integer; StdCall;
-
- PHostEnt = ^THostEnt;
- THostEnt = Packed Record
- Name: PChar;
- Aliases: ^PChar;
- AddrType: Smallint;
- Length: Smallint;
- Case Byte of
- 0 : (AddrList : ^PChar);
- 1 : (Addr : ^PChar);
- End;
-
- TGetHostByName = Function(Name : PChar) : PHostEnt; StdCall;
-
- Function GetWinSockInfo : String;
- Var
- WSLib : THandle;
- StartFunc : TWSAStartup;
- CleanFunc : TWSACleanup;
- GetNameFunc : TGetHostByName;
- Buf : Array[0..400] of Char;
- P : PHostEnt;
-
- Begin
- Result := '';
- WSLib := LoadLibrary('wsock32.dll');
- If (WSLib = 0) Then Begin
- Result := 'Cannot load "wsock32.dll": '+SysErrorMessage(GetLastError);
- Exit;
- End;
- StartFunc := GetProcAddress(WSLib,'WSAStartup');
- CleanFunc := GetProcAddress(WSLib,'WSACleanup');
- GetNameFunc := GetProcAddress(WSLib,'gethostbyname');
- StartFunc($0101,@Buf);
- With PWSAData(@Buf)^ do Begin
- Result := 'Version: '+IntToStr(LoByte(HighVersion))+'.'+IntToStr(HiByte(HighVersion))+#13#10+
- 'Description: '+String(Description)+#13#10+
- 'System status: '+String(SystemStatus);
- End;
- P := GetNameFunc(PChar(CurrentHostName)); { CHN is initialized by GetSystemInfo }
- If (P <> nil) Then Begin
- With P^ do Begin
- Move(Addr^^,Buf,4); { double pointer dereference }
- Result := Result+#13#10+'Host name: '+Name+#13#10+
- 'IP address: '+IntToStr(Ord(Buf[0]))+'.'+IntToStr(Ord(Buf[1]))+'.'+
- IntToStr(Ord(Buf[2]))+'.'+IntToStr(Ord(Buf[3]));
- End;
- End;
- CleanFunc;
- FreeLibrary(WSLib);
- End;
-
- Type
- TGetConnectedState = Function(Var Flags : Integer; Reserved : Integer) : Bool; StdCall;
-
- Const
- Internet_Connection_Modem = 1;
- Internet_Connection_LAN = 2;
- Internet_Connection_Proxy = 4;
-
- Function GetInternetConnectionInfo : String;
- Var
- WILib : THandle;
- GetCS : TGetConnectedState;
- State : Integer;
-
- Begin
- WILib := LoadLibrary('wininet.dll');
- If (WILib = 0) Then Begin
- Result := 'Cannot load "wininet.dll": '+SysErrorMessage(GetLastError);
- Exit;
- End;
- GetCS := GetProcAddress(WILib,'InternetGetConnectedState');
- If (@GetCS <> nil) Then Begin
- Result := 'Connected to Internet: ';
- If GetCS(State,0) Then Begin
- Result := Result+'Yes, with ';
- If ((State And Internet_Connection_Modem) <> 0) Then
- Result := Result+'modem, ';
- If ((State And Internet_Connection_LAN) <> 0) Then
- Result := Result+'LAN, ';
- If ((State And Internet_Connection_Proxy) <> 0) Then
- Result := Result+'proxy, ';
- SetLength(Result,Length(Result)-2); { remove comma & space }
- End
- Else Result := Result+'No';
- End
- Else Result := 'Cannot find function "InternetGetConnectedState" from WinInet:'+
- SysErrorMessage(GetLastError);
- FreeLibrary(WILib);
- End;
-
- end.
-